package encoding_protocol

import (
	"bytes"
	"encoding/binary"
)

type Response struct {
	headerLength uint32
	bodyLength   uint32
	MessageId    uint32
	Version      uint8
	Compressor   uint8
	Serializer   uint8

	Err  string
	Data []byte
}

func (r *Response) calculateHeaderLength() {
	length := 15 // 定长15

	if r.Err != "" {
		length += len(r.Err) + 1
	}
	r.headerLength = uint32(length)
}

func (r *Response) Encode() []byte {
	r.calculateHeaderLength()
	r.bodyLength = uint32(len(r.Data))
	bs := make([]byte, r.headerLength+r.bodyLength)
	binary.BigEndian.PutUint32(bs[0:4], r.headerLength)
	binary.BigEndian.PutUint32(bs[4:8], r.bodyLength)
	binary.BigEndian.PutUint32(bs[8:12], r.MessageId)
	bs[12] = r.Version
	bs[13] = r.Compressor
	bs[14] = r.Serializer

	if len(r.Err) > 0 {
		val := bs[15:]
		copy(val[0:len(r.Err)], r.Err)
		val[len(r.Err)] = separator

		if r.bodyLength > 0 {
			val = val[len(r.Err)+1:]
			copy(val[0:], r.Data)
		}
	} else {
		if r.bodyLength > 0 {
			copy(bs[15:], r.Data)
		}
	}
	return bs
}

func (r *Response) Decode(b []byte) error {
	r.headerLength = binary.BigEndian.Uint32(b[0:4])
	r.bodyLength = binary.BigEndian.Uint32(b[4:8])
	r.MessageId = binary.BigEndian.Uint32(b[8:12])
	r.Version = b[12]
	r.Compressor = b[13]
	r.Serializer = b[14]

	sliceBs := b[15:]
	idx := bytes.IndexByte(sliceBs, separator)
	if idx < 0 { // 没有err
		r.Data = sliceBs[0:]

		return nil
	}
	r.Err = string(sliceBs[:idx])
	sliceBs = sliceBs[idx+1:]

	r.Data = sliceBs[0:]

	return nil
}
